import os
import csv
import uuid
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import chardet
from parse_data_png import Gantry


def get_match_data(path):
    # 使用 chardet 检测文件编码
    with open(path, 'rb') as f:
        result = chardet.detect(f.read(10000))
    detected_encoding = result['encoding']
    # 使用检测到的编码读取 CSV 文件
    df = pd.read_csv(path, encoding=detected_encoding)
    df_np = df.to_numpy()
    return df_np


class Preprocess:
    def __init__(self, file_path):
        self.file_path = file_path
        self.up_gantry = None
        self.down_gantry = None
        self.up_gantry_df = None
        self.down_gantry_df = None
        self.max_speed = 120
        self.dist = None

    def get_gantry_ID(self):
        file_name = os.path.basename(self.file_path)
        # 使用逗号分隔字符串
        parts = file_name.split(',')
        # 提取前两个部分
        self.up_gantry = parts[0]
        self.down_gantry = parts[1].split('-')[0]  # 使用连字符进一步分割第二个部分

    def get_data(self):
        # 使用pandas读取CSV文件
        df = pd.read_csv(self.file_path, sep=',')
        # 清理列名，去除多余的空格和逗号
        df.columns = [col.strip().replace(',', '') for col in df.columns]
        # 清理每行数据中的多余符号
        # for col in df.columns:
        #     df[col] = df[col].str.strip(', ')
        # # 筛选 gantryid 列值为 up_gantry 的所有行
        self.up_gantry_df = df[df['gantryid'] == self.up_gantry]
        self.down_gantry_df = df[df['gantryid'] == self.down_gantry]

    def get_flow(self, df, time_interval):
        # 将transtime列转换为datetime类型
        df['transtime'] = pd.to_datetime(df['transtime'], format='%Y-%m-%d %H:%M:%S')
        # 假设我们按每10分钟统计一次流量
        # 使用pd.Grouper(freq='10T')来定义10分钟的时间窗口, 然后使用size()计算每个时间窗口内的车辆数量, 并重置索引
        grouped = df.groupby([pd.Grouper(key='transtime', freq=time_interval), 'feevehicletype']).size().unstack(fill_value=0)
        # 计算总车流量
        total_flow = grouped.sum(axis=1)
        # 计算各车型占比
        vehicle_percentage = grouped.div(total_flow, axis=0)

        return total_flow, vehicle_percentage

    def matching_json(self, up_gantry_df, down_gantry_df, up_path, down_path, up_flag=True, down_flag=True):
        up_gantry_df['transtime'] = pd.to_datetime(up_gantry_df['transtime'], format='%Y-%m-%d %H:%M:%S')
        up_gantry_df['timestamp'] = up_gantry_df['transtime'].apply(lambda x: x.timestamp())
        up_gantry_df_dict = up_gantry_df.to_dict(orient='records')
        down_gantry_df['transtime'] = pd.to_datetime(down_gantry_df['transtime'], format='%Y-%m-%d %H:%M:%S')
        down_gantry_df['timestamp'] = down_gantry_df['transtime'].apply(lambda x: x.timestamp())
        down_gantry_df_dict = down_gantry_df.to_dict(orient='records')

        # 对上游vlp去重
        up_gantry_df_dict_all = {}
        repeat_list_up = []
        for up_gantry_one in up_gantry_df_dict:
            if up_gantry_one['vlp'] not in up_gantry_df_dict_all.keys():
                up_gantry_df_dict_all[up_gantry_one['vlp']] = [up_gantry_one]
            else:
                # print("多趟次上游", up_gantry_one['vlp'])
                if up_gantry_one['vlp'] not in repeat_list_up:
                    repeat_list_up.append(up_gantry_one['vlp'])
                up_gantry_df_dict_all[up_gantry_one['vlp']].append(up_gantry_one)
        # print("重复上游", repeat_list_up)

        # 对下游vlp去重
        down_gantry_df_dict_all = {}
        repeat_list_down = []
        for down_gantry_one in down_gantry_df_dict:
            if down_gantry_one['vlp'] not in down_gantry_df_dict_all.keys():
                down_gantry_df_dict_all[down_gantry_one['vlp']] = [down_gantry_one]
            else:
                # print("多趟次下游", down_gantry_one['vlp'])
                if down_gantry_one['vlp'] not in repeat_list_down:
                    repeat_list_down.append(down_gantry_one['vlp'])
                down_gantry_df_dict_all[down_gantry_one['vlp']].append(down_gantry_one)
        # print("重复下游", repeat_list_down)

        for repeat_id in repeat_list_up:
            if repeat_id in down_gantry_df_dict_all.keys():
                # 上游匹配下游
                up_gantry_df_dict_list = up_gantry_df_dict_all[repeat_id]   # 多个
                down_gantry_df_dict_list = down_gantry_df_dict_all[repeat_id]   # 一个或多个
                for up_one in up_gantry_df_dict_list:
                    up_one_time = up_one['timestamp']
                    min_diff = 100000
                    target_one = None
                    for down_one in down_gantry_df_dict_list:
                        down_one_time = down_one['timestamp']
                        if up_one_time < down_one_time:
                            diff = down_one_time - up_one_time
                            if diff < min_diff:
                                min_diff = diff
                                target_one = down_one

                    uuid_one = str(uuid.uuid4())
                    if target_one is not None:
                        up_gantry_df_dict_all[repeat_id + uuid_one] = [up_one]
                        down_gantry_df_dict_all[repeat_id + uuid_one] = [target_one]
                        # print("匹配成功", up_one['vlp'], target_one['vlp'])
                        down_gantry_df_dict_all[repeat_id] = [x for x in down_gantry_df_dict_all[repeat_id] if x != target_one]
                    else:
                        # print("匹配失败", up_one['vlp'])
                        up_gantry_df_dict_all[repeat_id + uuid_one] = [up_one]

                # print("删除重复车辆", repeat_id)
                del up_gantry_df_dict_all[repeat_id]
                if len(down_gantry_df_dict_all[repeat_id]) == 0:
                    del down_gantry_df_dict_all[repeat_id]
            else:
                # print("上游多趟次车辆未在下游出现", repeat_id)
                pass

        for repeat_id in repeat_list_down:
            if repeat_id in down_gantry_df_dict_all.keys():
                if repeat_id in up_gantry_df_dict_all.keys():
                    down_gantry_df_dict_list = down_gantry_df_dict_all[repeat_id]   # 多个
                    up_gantry_df_dict_list = up_gantry_df_dict_all[repeat_id]   # 一个
                    for up_one in up_gantry_df_dict_list:
                        up_one_time = up_one['timestamp']
                        min_diff = 100000
                        target_one = None
                        for down_one in down_gantry_df_dict_list:
                            down_one_time = down_one['timestamp']
                            if up_one_time < down_one_time:
                                diff = down_one_time - up_one_time
                                if diff < min_diff:
                                    min_diff = diff
                                    target_one = down_one

                        if target_one is not None:
                            uuid_one = str(uuid.uuid4())
                            up_gantry_df_dict_all[repeat_id + uuid_one] = [up_one]
                            down_gantry_df_dict_all[repeat_id + uuid_one] = [target_one]
                            for i in range(len(down_gantry_df_dict_all[repeat_id])):
                                if down_gantry_df_dict_all[repeat_id][i] != target_one:
                                    uuid_two = str(uuid.uuid4())
                                    down_gantry_df_dict_all[repeat_id + uuid_two] = [down_gantry_df_dict_all[repeat_id][i]]
                        else:
                            # print("下游匹配失败ID", repeat_id)
                            for i in range(len(down_gantry_df_dict_all[repeat_id])):
                                    uuid_two = str(uuid.uuid4())
                                    down_gantry_df_dict_all[repeat_id + uuid_two] = [down_gantry_df_dict_all[repeat_id][i]]
                    # print("删除重复车辆", repeat_id)
                    del up_gantry_df_dict_all[repeat_id]
                    del down_gantry_df_dict_all[repeat_id]
                else:
                    # print("下游多趟次车辆未在上游出现", repeat_id)
                    pass
            else:
                # print("下游多趟次车辆与上游多趟次车辆一一匹配", repeat_id)
                pass

        if up_flag:
            time_list = []
            for lience, info in up_gantry_df_dict_all.items():
                if lience in down_gantry_df_dict_all.keys():
                    # print("匹配成功", lience, down_gantry_df_dict_all[lience][0]['timestamp'] - info[0]['timestamp'])
                    time_list.append(down_gantry_df_dict_all[lience][0]['timestamp'] - info[0]['timestamp'])
            time_mean = np.mean(time_list)
            print("平均行驶时间（s）", time_mean)

            result = []
            for lience, info in up_gantry_df_dict_all.items():
                if lience in down_gantry_df_dict_all.keys():
                    # print("匹配成功", lience, down_gantry_df_dict_all[lience][0]['timestamp'] - info[0]['timestamp'])
                    to_write = info[0]
                    fen = int((down_gantry_df_dict_all[lience][0]['timestamp'] - info[0]['timestamp']) / 60)
                    miao = int((down_gantry_df_dict_all[lience][0]['timestamp'] - info[0]['timestamp']) % 60)
                    temp = str(fen) + "m" + str(miao) + "s"
                    to_write['time_diff'] = temp
                    to_write['transtime_down'] = down_gantry_df_dict_all[lience][0]['transtime']
                    to_write['transtime_up'] = to_write['transtime']

                    if down_gantry_df_dict_all[lience][0]['timestamp'] - info[0]['timestamp'] < time_mean:
                        to_write['match_type'] = 0
                    if time_mean <= down_gantry_df_dict_all[lience][0]['timestamp'] - info[0][
                        'timestamp'] < time_mean * 1.5:
                        to_write['match_type'] = 1
                    if time_mean * 1.5 <= down_gantry_df_dict_all[lience][0]['timestamp'] - info[0][
                        'timestamp'] < time_mean * 3:
                        to_write['match_type'] = 2
                    if time_mean * 3 <= down_gantry_df_dict_all[lience][0]['timestamp'] - info[0]['timestamp']:
                        to_write['match_type'] = 3
                    if down_gantry_df_dict_all[lience][0]['timestamp'] < info[0]['timestamp']:
                        to_write['match_type'] = -2
                    if "警" in lience:
                        if lience[2] == '9':
                            to_write['police_car'] = 1
                        else:
                            to_write['police_car'] = 2
                    else:
                        to_write['police_car'] = 0

                    result.append(to_write)

                else:
                    # print("匹配失败", lience)
                    to_write = info[0]
                    to_write['time_diff'] = ""
                    to_write['transtime_down'] = ""
                    to_write['transtime_up'] = to_write['transtime']
                    to_write['match_type'] = -1
                    if "警" in lience:
                        if lience[2] == '9':
                            to_write['police_car'] = 1
                        else:
                            to_write['police_car'] = 2
                    else:
                        to_write['police_car'] = 0
                    result.append(to_write)
            df = pd.DataFrame(result)
            # 保存 DataFrame 到 CSV 文件
            output_file_path = up_path  # 替换为实际文件路径
            df[['vlp', 'feevehicletype', 'transtime_up', 'transtime_down', 'time_diff', 'match_type', 'police_car']].to_csv(output_file_path, index=False, encoding='utf-8')
        if down_flag:
            time_list = []
            for lience, info in down_gantry_df_dict_all.items():
                if lience in up_gantry_df_dict_all.keys():
                    time_list.append(info[0]['timestamp'] - up_gantry_df_dict_all[lience][0]['timestamp'])
            time_mean = np.mean(time_list)
            print("平均时间", time_mean)
            result = []

            for lience, info in down_gantry_df_dict_all.items():
                if lience in up_gantry_df_dict_all.keys():
                    to_write = info[0]
                    fen = int((info[0]['timestamp'] - up_gantry_df_dict_all[lience][0]['timestamp']) / 60)
                    miao = int((info[0]['timestamp'] - up_gantry_df_dict_all[lience][0]['timestamp']) % 60)
                    temp = str(fen) + "m" + str(miao) + "s"
                    if info[0]['timestamp'] - up_gantry_df_dict_all[lience][0]['timestamp'] < time_mean:
                        to_write['match_type'] = 0
                    if time_mean <= info[0]['timestamp'] - up_gantry_df_dict_all[lience][0][
                        'timestamp'] < time_mean * 1.5:
                        to_write['match_type'] = 1
                    if time_mean * 1.5 <= info[0]['timestamp'] - up_gantry_df_dict_all[lience][0][
                        'timestamp'] < time_mean * 3:
                        to_write['match_type'] = 2
                    if time_mean * 3 <= info[0]['timestamp'] - up_gantry_df_dict_all[lience][0]['timestamp']:
                        to_write['match_type'] = 3
                    if info[0]['timestamp'] < up_gantry_df_dict_all[lience][0]['timestamp']:
                        to_write['match_type'] = -2
                    if "警" in lience:
                        if lience[2] == '9':
                            to_write['police_car'] = 1
                        else:
                            to_write['police_car'] = 2
                    else:
                        to_write['police_car'] = 0
                    to_write['time_diff'] = temp
                    to_write['transtime_up'] = up_gantry_df_dict_all[lience][0]['transtime']
                    to_write['transtime_down'] = to_write['transtime']
                    result.append(to_write)
                else:
                    # print("匹配失败", lience)
                    to_write = info[0]
                    to_write['time_diff'] = ""
                    to_write['transtime_up'] = ""
                    to_write['transtime_down'] = to_write['transtime']
                    to_write['match_type'] = -1
                    if "警" in lience:
                        if lience[2] == '9':
                            to_write['police_car'] = 1
                        else:
                            to_write['police_car'] = 2
                    else:
                        to_write['police_car'] = 0
                    result.append(to_write)
            df = pd.DataFrame(result)
            # 保存 DataFrame 到 CSV 文件
            output_file_path = down_path  # 替换为实际文件路径
            df[['vlp', 'feevehicletype', 'transtime_up', 'transtime_down', 'time_diff', 'match_type', 'police_car']].to_csv(output_file_path, index=False, encoding='utf-8')

    def megred(self, up_path, down_path, all_path, flag=1):
        # 将上下游匹配数据合并为一个总文件
        up_data = get_match_data(up_path).copy()
        down_data = get_match_data(down_path).copy()
        # 提取时间戳列
        timestamps = up_data[:, 2]
        # 将时间戳列转换为 pandas.Timestamp 对象
        timestamps = pd.to_datetime(timestamps, format='%Y-%m-%d %H:%M:%S')
        # 使用 argsort 方法获取排序后的索引
        sort_indices = np.argsort(timestamps)
        # 根据排序后的索引对整个数组进行排序
        sorted_data = up_data[sort_indices]
        # 根据上游时间戳排序插入部分下游车辆到csv中
        up_time_list = []
        for row in sorted_data:
            up_time_list.append(pd.to_datetime(row[2], format='%Y-%m-%d %H:%M:%S'))
        time_list = [up_time_list, 0]
        i = 0
        # 遍历原始数组
        for row in down_data:
            if type(row[2]) == str:
                continue
            new_row_time = pd.to_datetime(row[3], format='%Y-%m-%d %H:%M:%S')
            # 使用 numpy.searchsorted 查找插入位置
            insert_index = np.searchsorted(time_list[flag], new_row_time)
            insert_position = insert_index + i
            i += 1
            sorted_data = np.insert(sorted_data, insert_position, row, axis=0)

        df = pd.DataFrame(sorted_data)

        # 定义新的列名映射
        new_column_names = {
            0: 'vlp',
            1: 'feevehicletype',
            2: 'transtime_up',
            3: 'transtime_down',
            4: 'time_diff',
            5: 'match_type',
            6: 'police_car'
        }

        # 修改列名
        df = df.rename(columns=new_column_names)
        # 保存 DataFrame 到 CSV 文件
        output_file_path = all_path  # 替换为实际文件路径
        df[['vlp', 'feevehicletype', 'transtime_up', 'transtime_down', 'time_diff', 'match_type', 'police_car']].to_csv(output_file_path, index=False, encoding='utf-8')

    def run(self, output_path):
        self.get_gantry_ID()
        self.get_data()

        # 生成上下游匹配csv文件
        file_name = os.path.basename(self.file_path)
        output = os.path.join(output_path, file_name.split('.')[0])
        if not os.path.exists(output):
            os.makedirs(output)
        up_path = os.path.join(output, 'up_' + file_name)
        down_path = os.path.join(output, 'down_' + file_name)
        all_path = os.path.join(output, 'all_' + file_name)
        print("output path: ", output)
        print(up_path, down_path, all_path)

        # 上下游各自匹配文件
        self.matching_json(self.up_gantry_df, self.down_gantry_df, up_path, down_path)

        # 合并文件 flag为0（根据上游时间戳排序）或1（根据下游时间戳排序）
        self.megred(up_path, down_path, all_path, flag=0)


if __name__ == '__main__':
    file_path = r'D:\hsy\06-大路网网格化\数据模拟\Log\G004251001000310010,G004251002000610010-20240429.csv'

    output_path = r'D:\hsy\06-大路网网格化\数据模拟\Log'
    preprocess = Preprocess(file_path)
    preprocess.run(output_path)

    root, ext = os.path.splitext(os.path.basename(file_path))
    dir_path = os.path.join(output_path, root)
    print("数据分析处理过程中... ...")
    gantry = Gantry(dir_path)
    gantry.run()
    print("save data and png in: ", dir_path)

